home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue30 / mmapfile / MMAPFILE.ZIP / E_MEMMAP.PAS next >
Encoding:
Pascal/Delphi Source File  |  1997-06-22  |  8.5 KB  |  262 lines

  1. unit E_MemMap;
  2. interface
  3. { This Unit implements an interface to Win32 memory mapped files. It
  4.   can be used to map data simply residing in memory or data residing
  5.   in a file. The data can be fully mapped into the processes address
  6.   space or chunks can be mapped. It also provides capabilities for
  7.   processes to synchronize via mutexes. When mapping sections of the
  8.   memory, you must be aware that the Win32 memory mapped file interface
  9.   requires that when you are requesting an offset into the memory
  10.   region, this offset must be a multiple of the system's memory
  11.   allocation granularity (I've called it PageSize). At this point
  12.   it is 64K. This is not a concern when you are mapping anything less
  13.   than 64K. However, to map anything > 64K the total memory size
  14.   mapped must be a multiple of 64K or you will not have access to
  15.   the memorysize MOD 64K bytes left over. Basically there are five
  16.   rules to be successful when using these routines:
  17.            1. Mapname must be unique for each different case you use
  18.               these objects (MyMap1 for case 1, MyMap2 for case 2
  19.               etc.).However, each process using the same memory map
  20.               MUST use the same MapName.
  21.            2. Call MapExisting before CreateMemMap or FCreateMemMap.
  22.               If another process has already started the mapping,
  23.               all you want to do is map to the existing map. ie.
  24.               If NOT MapExisting then CreateMemMap.
  25.            3. If your processes are going to write to the mapped
  26.               memory, it is suggested you use the mutex stuff.
  27.            4. Pay heed to the warning above concerning seeking
  28.               offsets into the mapped memory. Whenever you call
  29.               the seek function, always check for an error. Errors
  30.               in mapping to the file will result in the Memmap
  31.               pointer being Nil.
  32.            5. You MUST call LeaveCriticalSection after calling
  33.               EnterCriticalSection or you will lock other processes wishing
  34.               to use the map into an infinite wait state. Always use
  35.               a Try..Finally block.
  36. }
  37. Uses
  38.    Classes,Windows;
  39. Const
  40.      hMemMap = $FFFFFFFF;
  41. Type
  42.    //Map to memory
  43.    TEMemMap = Class(TComponent)
  44.    Private
  45.       FhFile          : THandle;   //File handle, hMemMap when simple memory
  46.       FhMap           : THandle;   //Mapping handle
  47.       FMap            : Pointer;   //Memory Pointer
  48.       FMapSize        : Cardinal;  //Mapping Page Size
  49.       FMemSize        : Cardinal;  //Maximum size allocated, >=FileSize when a file
  50.       FPageSize       : Cardinal;  //Minimum System allocation size
  51.       FMaxSeeks       : Cardinal;  //Maximum seeks available,(FMemSize DIV PageSize)-1
  52.       FMapError       : Integer;   //Error returned
  53.       FhMutex         : THandle;   //Mutex handle for sharing
  54.       FInMutex        : Boolean;   //Internal flag
  55.       Function SetMapError : Boolean;
  56.       Procedure SetMemSize(Size : Cardinal);
  57.    Public
  58.       Constructor Create(Aowner : TComponent); Override;
  59.       Destructor Destroy; Override;
  60.       //Create a mutex for sychronizing access
  61.       Function CreateMutex(Const MutexName : String) : Boolean;
  62.       //Use the mutex
  63.       Procedure EnterCriticalSection;
  64.       //Release the mutex
  65.       Procedure LeaveCriticalSection;
  66.       //Map to existing memory map
  67.       Function MapExisting(Const MapName : String;
  68.                            Const MapSize : Cardinal) : Boolean;Virtual;
  69.       //Create a new memory map
  70.       Function CreateMemMap(Const MapName : String;
  71.                             Const MapSize : Cardinal;
  72.                             Const MapData ) : Boolean;Virtual;
  73.       //seek to an offset in the memory map
  74.       Function Seek(Const OffSet : Cardinal) : Boolean;
  75.       //duh?
  76.       Procedure RaiseMappingException;Virtual;
  77.  
  78.       Property MemMap     : Pointer  Read FMap; //The mapped memory
  79.       Property MapError   : Integer  Read FMapError Write FMapError;
  80.       Property MemSize    : Cardinal Read FMemSize  Write SetMemSize; //Memory size to allocate
  81.       Property PageSize : Cardinal Read FPageSize; //system returned page size
  82.       Property MaxSeeks : Cardinal Read FMaxSeeks; //maximum seeks allowed
  83.    end;
  84.    //map to a file
  85.    TEFileMap = Class(TEMemMap)
  86.    Public
  87.       Function FCreateMemMap(Const Filename : String;
  88.                              Const MapName  : String;
  89.                              Const MapSize  : Cardinal) : Boolean;
  90.  
  91.       Function FlushFileView : Boolean;
  92.    end;
  93. implementation
  94. Uses
  95.     SysUtils;
  96. Type
  97.    EMappingException = class(Exception);
  98. Constructor TEMemMap.Create(AOwner : TComponent);
  99. Var
  100.     SysInfo : TSystemInfo;
  101. begin
  102.   Inherited Create(AOwner);
  103.   FhFile:=hMemMap;
  104.   GetSystemInfo(SysInfo);
  105.   FPageSize:=SysInfo.dwAllocationGranularity;
  106. end;
  107. Destructor TEMemmap.Destroy;
  108. begin
  109.   LeaveCriticalSection;
  110.   If FhMutex<>0 then
  111.     CloseHandle(FhMutex);
  112.   If FMap<>Nil then
  113.     UnMapViewOfFile(FMap);
  114.   If FHMap<>0 then
  115.     CloseHandle(FHMap);
  116.   Inherited Destroy;
  117. end;
  118. Function TEMemMap.CreateMutex(Const MutexName : String) : Boolean;
  119. begin
  120.   If FhMutex=0 then
  121.     FhMutex:=Windows.CreateMutex(Nil,False,PChar(MutexName));
  122.   If FhMutex=0 then
  123.     Result:=SetMapError
  124.   else
  125.     Result:=True;
  126. end;
  127. Procedure TEMemMap.EnterCriticalSection;
  128. begin
  129.   If (NOT FInMutex) AND (FhMutex>0) then
  130.   begin
  131.     WaitForSingleObject(FhMutex,INFINITE);
  132.     FInMutex:=True;
  133.   end;
  134. end;
  135. Procedure TEMemMap.LeaveCriticalSection;
  136. begin
  137.   If FInMutex AND (FhMutex>0) then
  138.   begin
  139.     ReleaseMutex(FhMutex);
  140.     FInMutex:=False;
  141.   end;
  142. end;
  143. Function TEMemMap.SetMapError : Boolean;
  144. begin
  145.   FMapError:=GetLastError;
  146.   Result:=False;
  147. end;
  148. Procedure TEMemMap.RaiseMappingException;
  149. Var
  150.     TError : Integer;
  151. begin
  152.   If FMapError<>0 then
  153.   begin
  154.     LeaveCriticalSection;
  155.     TError:=FMapError;
  156.     FMapError:=0;
  157.     Raise EMappingException.Create('Memory Mapping Error #'+IntToStr(TError));
  158.   end;
  159. end;
  160. Procedure TEMemMap.SetMemSize(Size : Cardinal);
  161. begin
  162.   FMemSize:=Size;
  163.   If FMemSize>PageSize then
  164.     FMaxSeeks:=(FMemSize DIV PageSize)-1
  165.   else
  166.     FMaxSeeks:=0;
  167. end;
  168. //map to an existing memory map described by MapName
  169. Function TEMemMap.MapExisting(Const MapName : String;
  170.                               Const MapSize : Cardinal) : Boolean;
  171. begin
  172.   FMapSize:=MapSize;
  173.   FMap:=Nil;
  174.   FhMap:=OpenFileMapping(FILE_MAP_WRITE,BOOL(True),PChar(MapName));
  175.   If FhMap<>0 then
  176.   begin
  177.     FMap:=MapViewOfFile(FhMap,FILE_MAP_WRITE,0,0,MapSize);
  178.     If FMap=Nil then
  179.     begin
  180.       CloseHandle(FHMap);
  181.       FHMap:=0;
  182.       SetMapError;
  183.     end;
  184.   end;
  185.   Result:=FMap<>Nil;
  186. end;
  187. //Create a new memory mapping
  188. Function TEMemMap.CreateMemMap(Const MapName : String;
  189.                                Const MapSize : Cardinal;
  190.                                Const MapData ) : Boolean;
  191. begin
  192.   If FMemSize=0 then
  193.     FMemSize:=MapSize;
  194.   FhMap:=CreateFileMapping(FhFile,nil,PAGE_READWRITE,0,FMemSize,PChar(MapName));
  195.   If FhMap<>0 then
  196.   begin
  197.     FMap:=MapViewOfFile(FhMap,FILE_MAP_WRITE,0,0,MapSize);
  198.     If FMap<>Nil then
  199.     begin
  200.       If fHFile=hMemMap then
  201.       begin
  202.         EnterCriticalSection;
  203.         Try
  204.           Move(MapData,FMap^,MapSize);
  205.         Finally
  206.           LeaveCriticalSection;
  207.         end;
  208.       end;
  209.       Result:=True;
  210.     end
  211.     else
  212.       Result:=SetMapError;
  213.   end
  214.   else
  215.     Result:=SetMapError;
  216. end;
  217. //seek to a different position in map (0..MaxSeeks)
  218. Function TEMemMap.Seek(Const OffSet : Cardinal) : Boolean;
  219. begin
  220.   Result:=True;
  221.   If NOT UnMapViewOfFile(FMap) then
  222.     Result:=SetMapError
  223.   else
  224.   begin
  225.     FMap:=MapViewOfFile(FhMap,FILE_MAP_WRITE,0,OffSet*PageSize,FMapSize);
  226.     If FMap=Nil then
  227.       Result:=SetMapError;
  228.   end;
  229. end;
  230. //Create a file mapping
  231. Function TEFileMap.FCreateMemMap(Const Filename : String;
  232.                                  Const MapName  : String;
  233.                                  Const MapSize  : Cardinal) : Boolean;
  234. Var
  235.     TInt  : Cardinal;
  236. begin
  237.   FHFile:=CreateFile(PChar(FileName),GENERIC_READ OR GENERIC_WRITE,
  238.                      FILE_SHARE_READ OR FILE_SHARE_WRITE,NIl,OPEN_EXISTING,
  239.                      FILE_FLAG_RANDOM_ACCESS,0);
  240.   If FhFile<>0 then
  241.   begin
  242.     Try
  243.       Result:=CreateMemMap(MapName,MapSize,TInt);
  244.     Finally
  245.       CloseHandle(FhFile);
  246.     end;
  247.   end
  248.   else
  249.     Result:=SetMapError;
  250. end;
  251.  
  252. Function TEFileMap.FlushFileView : Boolean;
  253. begin
  254.   EnterCriticalSection;
  255.   Try
  256.     Result:=FlushViewOfFile(FMap,FMapSize) OR SetMapError;
  257.   Finally
  258.     LeaveCriticalSection;
  259.   end;
  260. end;
  261. end.
  262.